home *** CD-ROM | disk | FTP | other *** search
- unit Names3u2;
-
- interface
-
- uses
- SysUtils;
-
- type
- TDataRec = packed record
- { The form's edit box has its MaxLength property set to 30 }
- Name: String[30];
- { Only interested in the date portion of this date/time value }
- DOB: TDateTime;
- end;
-
- TDataFile = class
- private
- FDataFile: Integer;
- protected
- function GetCount: Longint;
- function GetCurrent: Longint;
- function GetRecord(Index: Longint): TDataRec;
- procedure SetCurrent(RecNo: Longint);
- procedure SetRecord(Index: Longint; const DataRec: TDataRec);
- public
- constructor Create;
- destructor Destroy; override;
- property Count: Longint read GetCount;
- property Current: Longint
- read GetCurrent write SetCurrent;
- property Records[Index: Longint]: TDataRec
- read GetRecord write SetRecord; default;
- end;
-
- implementation
-
- uses
- WinProcs, Forms, NetLock, Consts, Classes;
-
- const
- FileName = 'DataFile.Dat';
-
- {$ifndef Win32}
- function GetFileSize(Handle: Integer): Longint;
- var
- OldPos, FileSize: Longint;
- begin
- Result := FileSeek(Handle, 0, soFromCurrent);
- if Result > -1 then
- begin
- OldPos := Result;
- FileSize := FileSeek(Handle, 0, soFromEnd);
- if FileSize > -1 then
- begin
- Result := FileSeek(Handle, OldPos, soFromBeginning);
- if Result > -1 then
- Result := FileSize;
- end;
- end;
- end;
- {$endif}
-
- constructor TDataFile.Create;
- begin
- { Make current directory where EXE file is, just in case }
- ChDir(ExtractFilePath(Application.ExeName));
- { Make file if it ain't there }
- if not FileExists(FileName) then
- FDataFile := FileCreate(FileName);
- if FDataFile < 0 then
- raise EFCreateError.Create(FmtLoadStr(SFCreateError, [FileName]));
- { Close handle returned by FileCreate so we can open it in shared mode }
- FileClose(FDataFile);
- FDataFile := FileOpen(FileName, fmOpenReadWrite or fmShareDenyNone);
- if FDataFile < 0 then
- raise EFOpenError.Create(FmtLoadStr(SFOpenError, [FileName]));
- end;
-
- destructor TDataFile.Destroy;
- begin
- FileClose(FDataFile);
- inherited Destroy;
- end;
-
- function TDataFile.GetCount: Longint;
- begin
- {$ifndef Win32}
- Result := GetFileSize(FDataFile) div SizeOf(TDataRec);
- {$else}
- Result := GetFileSize(FDataFile, nil) div SizeOf(TDataRec);
- {$endif}
- end;
-
- function TDataFile.GetCurrent: Longint;
- begin
- Result := FileSeek(FDataFile, 0, soFromCurrent);
- if Result > -1 then
- Result := Result div SizeOf(TDataRec);
- end;
-
- function TDataFile.GetRecord(Index: Longint): TDataRec;
- begin
- Current := Index;
- if FileRead(FDataFile, Result, SizeOf(TDataRec)) < SizeOf(TDataRec) then
- raise EListError.CreateRes(SListIndexError);
- { Go back to the beginning of the read record }
- Current := Index;
- end;
-
- procedure TDataFile.SetCurrent(RecNo: Longint);
- begin
- { Anything past EOF is considered EOF }
- if RecNo > Count then
- RecNo := Count;
- FileSeek(FDataFile, RecNo * SizeOf(TDataRec), soFromBeginning);
- end;
-
- procedure TDataFile.SetRecord(Index: Longint; const DataRec: TDataRec);
- var
- X: EInOutError;
- begin
- Current := Index;
- if not LockFileArea(FDataFile, Current * SizeOf(TDataRec),
- SizeOf(TDataRec), False) then
- begin
- X := EInOutError.Create('Cannot lock file');
- { Set up a file access denied type exception }
- X.ErrorCode := 5;
- raise X;
- end;
- try
- { DataRec is passed as a const (pass by reference, but }
- { not allowed to be treated/passed as a var parameter). }
- { We can get around this by dereferencing its }
- { address with an appropriate typecast }
- if FileWrite(FDataFile, DataRec, SizeOf(TDataRec)) < SizeOf(TDataRec) then
- raise EInOutError.Create('Cannot write to file');
- { Go back to the beginning of the written record }
- Current := Index;
- finally
- LockFileArea(FDataFile, Current * SizeOf(TDataRec),
- SizeOf(TDataRec), True);
- end;
- end;
-
- end.